package ace.tool.generate.code.impl.generator.graphql;

import ace.cmp.util.CaseFormatUtils;
import ace.tool.generate.code.impl.generator.AbstractGenerator;
import ace.tool.generate.code.impl.generator.graphql.model.GraphqlAdminControllerModel;
import ace.tool.generate.code.impl.resolver.TemplateModelClassResolver;
import ace.tool.generate.code.impl.resolver.impl.TemplateModelDataJdbcClassResolverImpl;
import ace.tool.generate.code.impl.resolver.model.TemplateModel;
import java.util.List;
import lombok.SneakyThrows;
import org.apache.commons.text.WordUtils;

/**
 * @author caspar
 * @date 2023/11/17 9:57 生成graphql schema admin controller 默认架构内容
 */
public class GraphqlAdminControllerGenerator
    extends AbstractGenerator<GraphqlAdminControllerGeneratorInput, GraphqlAdminControllerModel> {

  private final TemplateModelClassResolver resolver = new TemplateModelDataJdbcClassResolverImpl();

  @Override
  public void generate(List<GraphqlAdminControllerGeneratorInput> graphqlSchemaGeneratorInputs) {
    throw new RuntimeException("不支持批量,请使用单个生成接口");
  }

  @Override
  protected GraphqlAdminControllerModel resolveModel(GraphqlAdminControllerGeneratorInput input) {

    TemplateModel templateModel = resolver.resolve(input.getParams());

    GraphqlAdminControllerModel model =
        GraphqlAdminControllerModel.builder()
            .packageFullName(this.getPackageFullName(input))
            .entityClassFullName(this.getEntityClassFullName(input))
            .schemaExtendMapping(this.getSchemaExtendMapping(input))
            .schemaExtendMappingSuffix(this.getSchemaExtendMappingSuffix(input))
            .controllerClassName(this.getControllerClassName(input))
            .controllerClassNameSuffix(this.getControllerClassNameSuffix(input))
            .entityClassName(this.getEntityClassName(input))
            .entityIdType(this.getEntityIdType(input, templateModel))
            .entityClassNameLowercaseUnderline(this.getEntityClassNameLowercaseUnderline(input))
            .securityIdentitySuffix(input.getSecurityIdentitySuffix())
            .build();

    return model;
  }

  private String getControllerClassName(GraphqlAdminControllerGeneratorInput input) {
    return input.getParams().getSimpleName();
  }

  private String getControllerClassNameSuffix(GraphqlAdminControllerGeneratorInput input) {
    return input.getControllerClassNameSuffix();
  }

  private String getEntityClassName(GraphqlAdminControllerGeneratorInput input) {
    return input.getParams().getSimpleName();
  }

  private String getEntityIdType(
      GraphqlAdminControllerGeneratorInput input, TemplateModel templateModel) {
    return templateModel.getFields().stream()
        .filter(p -> Boolean.TRUE.equals(p.getIdFlag()))
        .findFirst()
        .get()
        .getType()
        .getName();
  }

  private String getEntityClassNameLowercaseUnderline(GraphqlAdminControllerGeneratorInput input) {
    return CaseFormatUtils.convertUpperCamelToLowerUnderscore(input.getParams().getSimpleName());
  }

  private String getSchemaExtendMappingSuffix(GraphqlAdminControllerGeneratorInput input) {
    return input.getSchemaExtendMappingSuffix();
  }

  private String getSchemaExtendMapping(GraphqlAdminControllerGeneratorInput input) {
    return WordUtils.uncapitalize(this.getControllerClassName(input));
  }

  private String getEntityClassFullName(GraphqlAdminControllerGeneratorInput input) {
    return input.getParams().getName();
  }

  @SneakyThrows
  private String getPackageFullName(GraphqlAdminControllerGeneratorInput input) {
    Package entityClassPackage = input.getParams().getPackage();
    String basePackageName =
        this.getParentPackageName(this.getParentPackageName(entityClassPackage.getName()));
    return String.format("%s%s", basePackageName, input.getPackageSuffix());
  }

  private String getParentPackageName(String packageName) {
    String[] packageArr = packageName.split("\\.");
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < packageArr.length - 1; i++) {
      if (sb.length() > 0) {
        sb.append(".");
      }
      sb.append(packageArr[i]);
    }
    return sb.toString();
  }

  @Override
  protected String getFileName(
      GraphqlAdminControllerGeneratorInput input, GraphqlAdminControllerModel schemaModel) {
    return this.getControllerClassName(input) + this.getControllerClassNameSuffix(input) + ".java";
  }

  @Override
  protected String getFileFullName(
      GraphqlAdminControllerGeneratorInput input, GraphqlAdminControllerModel model) {
    String fileName = this.getFileName(input, model);
    String packageFullName = this.getPackageFullName(input);
    String packageFullDirName = packageFullName.replaceAll("\\.", "/");
    return String.format("%s/%s/%s", input.getOutputDir(), packageFullDirName, fileName);
  }
}
